package com.dongrj.framework.core.utils;

import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author dongrongjun
 * @date 2020/08/04
 */
@Slf4j
public final class FileUtils {

    /**
     * 获取文件分隔符
     */
    public static String getSeparator() {
        return File.separator;
    }

    /**
     * 根据文件路径获取文件Path
     *
     * @param filePath 文件路径
     */
    public static Path getPath(String filePath) {
        return Paths.get(filePath);
    }

    /**
     * 根据文件路径获取文件Path
     *
     * @param filePath 文件路径
     * @param others   其他文件路径
     */
    public static Path getPath(String filePath, String... others) {
        return Paths.get(filePath, others);
    }


    /**
     * 获取分隔符的路径
     *
     * @param paths 路径
     */
    public static String getPath(List<String> paths) {
        if (CollectionUtils.isEmpty(paths)) {
            return "";
        }
        return Joiner.on(getSeparator()).join(paths);
    }

    /**
     * 判断文件路径是否存在
     *
     * @param filePath 文件路径
     */
    public static boolean pathExists(String filePath) {
        Optional<File> file = getFile(filePath);
        return file.isPresent();
    }

    /**
     * 根据文件路径获取文件
     *
     * @param filePath 文件路径
     */
    public static Optional<File> getFile(String filePath) {
        final File file = getPath(filePath).toFile();
        if (file.exists()) {
            return Optional.of(file);
        }
        return Optional.empty();
    }

    /**
     * 根据文件路径获取文件内容
     *
     * @param filePath 文件路径
     */
    public static <T> List<T> map(String filePath, Function<String, T> function) {
        final Path path = getPath(filePath);
        try (Stream<String> stream = Files.lines(path)) {
            return stream.map(function).collect(Collectors.toList());
        } catch (IOException e) {
            log.error("toMap error, from{} error,{}", path, e.getMessage());
        }
        return Lists.newArrayList();
    }

    /**
     * 根据文件路径获取文件内容
     *
     * @param filePath 文件路径
     */
    public static <T> void forEach(String filePath, Consumer<String> consumer) {
        final Path path = getPath(filePath);
        try (Stream<String> stream = Files.lines(path)) {
            stream.forEach(consumer);
        } catch (IOException e) {
            log.error("toMap error, from{} error,{}", path, e.getMessage());
        }
    }


    /**
     * 根据文件路径获取文件内容
     *
     * @param filePath 文件路径
     */
    public static List<String> getFileLines(String filePath) {
        final Path path = getPath(filePath);
        try (Stream<String> stream = Files.lines(path)) {
            return stream.collect(Collectors.toList());
        } catch (IOException e) {
            log.error("get content from{} error,{}", path, e.getMessage());
        }
        return Lists.newArrayList();
    }


    /**
     * 根据文件路径获取文件内容
     *
     * @param filePath 文件路径
     */
    public static List<String> getFileLines(String filePath, long skip, long limit) {
        final Path path = getPath(filePath);
        try (Stream<String> stream = Files.lines(path)) {
            return stream.skip(skip).limit(limit).collect(Collectors.toList());
        } catch (IOException e) {
            log.error("get content from{} error,{}", path, e.getMessage());
        }
        return Lists.newArrayList();
    }


    /**
     * 根据文件路径写入文件内容
     *
     * @param filePath  文件路径
     * @param fileLines 文件内容
     */
    public static void writeFile(String filePath, List<String> fileLines) {
        try {
            Files.write(getPath(filePath), fileLines, StandardOpenOption.TRUNCATE_EXISTING);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 文件路径获取文件名
     *
     * @param filePath 文件路径
     */
    public static String getFileName(String filePath) {
        Path path = getPath(filePath);
        File file = path.toFile();
        if (file.exists()) {
            return file.getName();
        }
        return "";
    }

    /**
     * 文件内容追加
     *
     * @param path 路径
     * @param line 内容
     */
    public static void append(Path path, String line) {
        append(path, Lists.newArrayList(line));
    }


    /**
     * 文件内容追加
     *
     * @param path  路径
     * @param lines 内容
     */
    public static void append(Path path, List<String> lines) {
        try {
            Files.write(path, lines, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 删除文件
     *
     * @param path 路径
     */
    public static void delete(Path path) {
        try {
            Files.delete(path);
            log.info("文件[{}]删除成功!", path);
        } catch (IOException e) {
            log.error("delete.e", e);
            throw new RuntimeException(String.format("文件[%s]删除失败!", path.toString()), e);
        }
    }

    /**
     * 删除文件
     *
     * @param path 路径
     */
    public static void delete(String path) {
        try {
            Path p = Paths.get(path);
            Files.delete(p);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("delete.e={}", e);
            throw new RuntimeException(String.format("文件[%s]删除失败!", path));
        }
    }


    /**
     * 根据文件路径下的文件
     *
     * @param dirPath 文件目录路径
     */
    public static List<File> getFileList(Path dirPath) {
        File folder = dirPath.toFile();
        File[] files = folder.listFiles();
        if (files == null || files.length == 0) {
            return Lists.newArrayList();
        }
        return Arrays.stream(files).collect(Collectors.toList());
    }


}
